package com.tfjybj.itoo.teach.provider.service.impl;

import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.dmsdbj.itoo.tool.base.service.impl.BaseServicePlusImpl;
import com.dmsdbj.itoo.tool.business.ItooResult;
import com.dmsdbj.itoo.tool.uuid.BaseUuidUtils;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.tfjybj.itoo.teach.entity.BuildingEntity;
import com.tfjybj.itoo.teach.model.BuildingModel;
import com.tfjybj.itoo.teach.model.FooGroupTreeModel;
import com.tfjybj.itoo.teach.model.InfoIntegrationTreeModel;
import com.tfjybj.itoo.teach.provider.dao.BuildingDao;
import com.tfjybj.itoo.teach.provider.dao.ValueDao;
import com.tfjybj.itoo.teach.provider.service.BuildingService;
import com.tfjybj.itoo.teach.template.BuildingExportTemplate;
import com.tfjybj.itoo.teach.template.BuildingInfoTemplate;
import lombok.extern.slf4j.Slf4j;
import org.jplus.hyberbin.excel.utils.ExcelUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.Serializable;
import java.util.*;

import static com.tfjybj.itoo.teach.provider.until.DemoConstants.*;

/**
 * BuildingService接口实现类
 * ${base}表
 *
 * @author 段恩刚
 * @version 2.0.0
 * @since 2.0.0 2018-11-08 19:34:10
 */
@Service("buildingService")
@Slf4j
public class BuildingServiceImpl extends BaseServicePlusImpl<BuildingDao, BuildingEntity> implements BuildingService {

    @Resource
    private BuildingDao buildingDao;

    @Resource
    private ValueDao valueDao;

    @Resource
    private RedisTemplate<String, BuildingInfoTemplate> redisTemplate;

	
	 @Override
    public PageInfo<BuildingEntity> queryByLikeName(String name, Integer pageNum, Integer pageSize) {
        PageHelper.startPage(pageNum, pageSize);
        return new PageInfo<>(buildingDao.queryLikeName(name));
    }
    //endregion

    /* **********************************以下为非模板生成的内容********************************* */
    /**
     * 根据校区Id查询所有该校区的所有建筑
     *
     * @param schoolBranch 校区Id
     * @return buildingModel
     * @author 段恩刚
     * @since 2.0.0 2018-11-13 19:34:10
     */
    @Override
    public List<BuildingModel> queryAllBuildings(String schoolBranch) {
        return buildingDao.queryAllBuildings(schoolBranch);
    }

    /**
     * 根据前十条建筑信息
     * param
     * @return buildingModel
     * @author 段恩刚
     * @since 2.0.0 2018-11-13 19:34:10
     */
    @Override
    public List<BuildingModel> queryTop10Buildings() {
        return buildingDao.queryTop10Buildings();
    }

    /**
     * 根据建筑名称查询建筑
     *
     * @param buildingName 建筑名称
     * @return buildingModel
     * @author 段恩刚
     * @since 2.0.0 2018-11-14 19:34:10
     */
    @Override
    public List<BuildingModel> queryBuildingByName(String buildingName) {
        return buildingDao.queryBuildingByName(buildingName);
    }

    /**
     * 根据建筑类型查询建筑
     *
     * @param buildingType 建筑类型
     * @return buildingModel
     * @author 段恩刚
     * @since 2.0.0 2018-11-15 19:34:10
     */
    @Override
    public List<BuildingModel> queryBuildingsByType(String buildingType) {
        return buildingDao.queryBuildingsByType(buildingType);
    }

    /**
     * 根据建筑名称或类型模糊查询building
     * @param buildingName  建筑名称
     * @param buildingType  建筑类型
     * @return buildingModel
     * @author 段恩刚
     * @since 2.0.0 2018-11-15 19:34:10
     */
    @Override
    public PageInfo<BuildingModel> queryBuildingsLikeNameOrType(String buildingName, String buildingType, Integer pageNum, Integer pageSize) {
        PageHelper.startPage(pageNum, pageSize);
        List<BuildingModel>buildingModelList=buildingDao.queryBuildingsLikeNameOrType(buildingName,buildingType);
        return new PageInfo<>(buildingModelList);
    }

    /**
     * 页面Roommanage加载时查询所有的buildingId
     * param
     * @return buildingModel
     * @author 段恩刚
     * @since 2.0.0 2018-11-13 19:34:10
     */
    @Override
    public List<BuildingModel> queryAllBuildingIds() {
        return buildingDao.queryAllBuildingIds();
    }

    /**
     * 场所管理页面的导出
     * @param  bulidingName
     * @return buildingModel
     * @author 段恩刚
     * @since 2.0.0 2018-11-13 19:34:10
     */
    @Override
    public boolean exportByLikeName(String bulidingName, HttpServletResponse response) {
        //获得要导出的fooList
        List<BuildingModel> buildingModels;
        if(bulidingName==""){
            buildingModels=buildingDao.queryAllBuildingIds();
        }
        else {
            buildingModels=buildingDao.queryBuildingsLikeNameOrType(bulidingName,"");
        }

        List<BuildingExportTemplate> buildingExportTemplates=new ArrayList<>();

        for(BuildingModel buildingModel:buildingModels){
            BuildingExportTemplate buildingExportTemplate=new BuildingExportTemplate();
            BeanUtils.copyProperties(buildingModel,buildingExportTemplate);
            buildingExportTemplate.setCode(buildingModel.getCode());
            buildingExportTemplate.setName(buildingModel.getName());
            buildingExportTemplate.setType(buildingModel.getType());
            buildingExportTemplate.setIsComputerRoom(buildingModel.getIsComputerRoom());
            buildingExportTemplate.setSchoolBranch(buildingModel.getSchoolBranch());
            buildingExportTemplates.add(buildingExportTemplate);
        }
        //导出
        Map<Serializable, Serializable> errorMap = new HashMap<>(16);
        errorMap.put(NAME, "场所信息");
        errorMap.put(SHEET_NAME, "场所信息");
        errorMap.put(TITLE, "场所的信息");
        errorMap.put(COLUMNS, new String[]{"code", "name", "type", "isComputerRoom", "schoolBranch"});
        errorMap.put(DATA_LIST, (Serializable) buildingExportTemplates);
        try {
            ExcelUtil.exportExcel(errorMap, response);
        } catch (Exception e) {
            return false;
        }
        return false;
    }

    /**
     * 下载培养计划模板，批量导入使用
     *
     * @param response 响应
     * @return 下载模板是否成功
     * @author 段恩刚
     * @since 2.0.0 2018-11-15 08:53:53
     */
    @Override
    public boolean downLoadTemplate(HttpServletResponse response) {
        Map<Serializable, Serializable> map = new HashMap<>(16);
        List<BuildingInfoTemplate> buildingInfoTemplateList = new ArrayList<>();
        BuildingInfoTemplate buildingInfoTemplate=new BuildingInfoTemplate();

        buildingInfoTemplate.setCode("11");
        buildingInfoTemplate.setName("数理楼");
        buildingInfoTemplate.setType("教学楼");
        buildingInfoTemplate.setIsComputerRoom(1);
        buildingInfoTemplate.setSchoolBranch("东校区");
        buildingInfoTemplateList.add(buildingInfoTemplate);


        //sheet的名字
        map.put(SHEET_NAME, "建筑信息");
        //需要导入的字段
        map.put(COLUMNS, new String[]{"code", "name", "type", "isComputerRoom", "schoolBranch"});
        //表格的标题
        map.put(TITLE, "建筑信息");
        map.put(NAME, "建筑信息模板");
        map.put(DATA_LIST, (Serializable) buildingInfoTemplateList);

        try {
            ExcelUtil.exportExcel(map, response);
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * 判断导入的信息是否为空
     *
     * @param excelTPT 需要导入的信息
     * @return boolean 导入的字段是否为空
     * @author 段恩刚
     * @since 2.0.0 2018/11/16 20:43
     */
    private boolean verify(BuildingInfoTemplate excelTPT )
    {
        if (StringUtils.isEmpty(excelTPT.getCode())) {
            excelTPT.setFailReason("建筑代码未填写");
            log.warn("导入失败,建筑代码未填写,excelFooEntity-{}", excelTPT);
            return false;
        }
        if (StringUtils.isEmpty(excelTPT.getName())) {
            excelTPT.setFailReason("建筑名称未填写");
            log.warn("导入失败,建筑名称未填写,excelFooEntity-{}", excelTPT);
            return false;
        }
        if (StringUtils.isEmpty(excelTPT.getType())) {
            excelTPT.setFailReason("建筑类型未填写");
            log.warn("导入失败,建筑未填写,excelFooEntity-{}", excelTPT);
            return false;
        }
        if (StringUtils.isEmpty(excelTPT.getIsComputerRoom() )) {
            excelTPT.setFailReason("是否有机房未填写");
            log.warn("导入失败,是否有机房未填写,excelFooEntity-{}", excelTPT);
            return false;
        }
        if (StringUtils.isEmpty(excelTPT.getSchoolBranch())) {
            excelTPT.setFailReason("是否有校区名称未填写");
            log.warn("导入失败,是否有校区名称未填写,excelFooEntity-{}", excelTPT);
            return false;
        }
        String buildingCode=excelTPT.getCode();
        String buildingName=excelTPT.getName();
        String isExist=buildingDao.findIdIsExist(buildingCode,buildingName);
        if (!StringUtils.isEmpty(isExist)) {
            excelTPT.setFailReason("建筑Code或名称重复");
            log.warn("导入失败,建筑Code或名称重复,excelFooEntity-{}", excelTPT);
            return false;
        }
        return true;
    }
    /**
     * 批量导入
     * @param
     * @return
     * @author 段恩刚
     * @since 2.0.0 2018/11/26 14:29
     */
    @Override
    public ItooResult importTemplate(MultipartFile multipartFile, HttpServletRequest request, HttpServletResponse response) {
        response.setContentType("UTF-8");
        try {
            //检验文件是否存在
            String fileName=multipartFile.getOriginalFilename();
            if (fileName==null){
                log.error("导入失败,fileName is null!");
                return ItooResult.build(ItooResult.FAIL, "传入的文件为空！");
            }
            //EXCEL解析成List
            Map<Serializable, Serializable> map = new HashMap<>(4);
            map.put(SHEET_NAME, "建筑信息");
            map.put(CLASS, BuildingInfoTemplate.class);

            List<BuildingInfoTemplate> buildingInfoTemplateList= ExcelUtil.importExcel(Objects.requireNonNull(fileName), map, request, response);

            if (buildingInfoTemplateList.size() == 0) {
                return ItooResult.build(ItooResult.FAIL, "导入的数据为空，请填写！");
            }
            //定义导入的错误数据集合并存redis中形式的<String,TrainingProgramsTemplate>
            List<BuildingInfoTemplate> errorTPTList = new ArrayList<>();
            String errorListId = BaseUuidUtils.base58Uuid();
            Long size = redisTemplate.opsForZSet().size(errorListId);
            size = size == null ? 0L : size;

            for(BuildingInfoTemplate excelTPT:buildingInfoTemplateList){

                if(!this.verify(excelTPT)){
                      BuildingInfoTemplate buildingInfoTemplateT=new BuildingInfoTemplate();
                      BeanUtils.copyProperties(excelTPT,buildingInfoTemplateT);

                      errorTPTList.add(buildingInfoTemplateT);
                      redisTemplate.opsForZSet().add(errorListId,buildingInfoTemplateT,size+1);
                      continue;
                }

                BuildingEntity buildingEntity =new BuildingEntity();

                //将导入内容放到entity中对应的属性中去
                BeanUtils.copyProperties(excelTPT,buildingEntity);

                //建筑信息的id
                buildingEntity.setId(IdWorker.getIdStr());
                //建筑未删除
                buildingEntity.setIsDelete(0);

                buildingEntity.setCode(excelTPT.getCode());
                buildingEntity.setName(excelTPT.getName());

                String buildingType="000";
                switch(excelTPT.getType()) {
                    case "教学楼":
                        buildingType="000";
                        break;
                    case "办公楼":
                        buildingType="001";
                        break;
                    case "宿舍楼":
                        buildingType="002";
                        break;
                    case "图书馆":
                        buildingType="003";
                        break;
                    case "餐厅":
                        buildingType="004";
                        break;
                    default:
                        break;
                }
                buildingEntity.setType(buildingType);

                String schoolBranch="010";
                switch(excelTPT.getSchoolBranch()) {
                    case "西校区":
                        schoolBranch="010";
                        break;
                    case "东校区":
                        schoolBranch="011";
                        break;
                    default:
                        break;
                }
                buildingEntity.setSchoolBranch(schoolBranch);
                buildingEntity.setIsComputerRoom(excelTPT.getIsComputerRoom());
              this.save(buildingEntity);
            }
            //不符合条件的信息返回
            if (!CollectionUtils.isEmpty(errorTPTList)) {
                return ItooResult.build("0001","部分导入失败",errorListId);
            }

        }
        catch (Exception e){
            return ItooResult.build(ItooResult.FAIL, "导入数据异常！",e);
        }
        return ItooResult.build(ItooResult.FAIL, "导入数据成功！");
    }

    /**
     * 根据建筑名称获取建筑Id
     *
     * @param buildingName 建筑名称
     * @return buildingId
     * @author 段恩刚
     * @since 2.0.0 2018-11-15 19:34:10
     */
    @Override
    public String queryBuildingIdByName(String buildingName) {
        return buildingDao.queryBuildingIdByName(buildingName);
    }

    /**
     * 导出错误数据
     *
     * @param response 响应
     * @param errorListId 为成功导入的分组id
     * @return 课程信息model
     * @author 段恩刚
     * @since 2018年11月30日11:32:54
     */
    @Override
    public boolean downErrorList(String errorListId, HttpServletResponse response) {
        // redis 取出没有成功导入的人员信息
        Set set = redisTemplate.opsForZSet().range(errorListId,0,-1);
        List<BuildingExportTemplate> buildingExportTemplates=new ArrayList<>(set);

        // 清空redis数据
        redisTemplate.delete(errorListId);

        //导出
        if (buildingExportTemplates.size() == 0){
            return false;
        }
        Map<Serializable,Serializable> errorMap = new HashMap<>(16);
        errorMap.put(NAME,"未导入的信息");
        errorMap.put(SHEET_NAME,"建筑信息");
        errorMap.put(TITLE,"未导入的信息");
        errorMap.put(COLUMNS,new String[]{"code", "name", "type", "isComputerRoom", "schoolBranch","failReason"});
        errorMap.put(DATA_LIST,(Serializable) buildingExportTemplates);
        try {
            ExcelUtil.exportExcel(errorMap, response);
        }catch (Exception e ){
            return false;
        }
        return true;
    }

    /**
     * 查询fooGroup的树形结构的所有信息
     * @return fooGroup的树形结构
     * @author 段恩刚
     * @since 1.0.0 2018-11-30 15:51:27
     */
    @Override
    public List<FooGroupTreeModel> queryTreeModel() {
        List<InfoIntegrationTreeModel> infoIntegrationTreeModels=buildingDao.queryTreeInfo();
        //转化为树形结构
        List<FooGroupTreeModel> fooGroupTreeModels=new ArrayList<>();

        for(InfoIntegrationTreeModel infoIntegrationTreeModel:infoIntegrationTreeModels){

            FooGroupTreeModel buildTree=new FooGroupTreeModel();
            FooGroupTreeModel roomTree=new FooGroupTreeModel();
            FooGroupTreeModel buildingTypeTree=new FooGroupTreeModel();

            //房屋和建筑
            roomTree.setId(infoIntegrationTreeModel.getRoomId());
            roomTree.setName(infoIntegrationTreeModel.getRoomName());
            roomTree.setParentId(infoIntegrationTreeModel.getBuildingId());
            roomTree.setOpen(false);
            fooGroupTreeModels.add(roomTree);

            //建筑和建筑类型
            buildTree.setId(infoIntegrationTreeModel.getBuildingId());
            buildTree.setName(infoIntegrationTreeModel.getBuildingName());
            buildTree.setParentId(infoIntegrationTreeModel.getBuildingTypeId());
            buildTree.setOpen(false);
            fooGroupTreeModels.add(buildTree);

            //建筑类型和校区
            buildingTypeTree.setId(infoIntegrationTreeModel.getBuildingTypeId());
            buildingTypeTree.setName(infoIntegrationTreeModel.getBuildingTypeName());
            buildingTypeTree.setParentId("111");
            buildingTypeTree.setOpen(true);
            fooGroupTreeModels.add(buildingTypeTree);

            //List去重
            for  ( int  i  =   0 ; i  <  fooGroupTreeModels.size()  -   1 ; i ++ )  {
                for  ( int  j  =  fooGroupTreeModels.size()  -   1 ; j  >  i; j -- )  {
                    if  (fooGroupTreeModels.get(j).equals(fooGroupTreeModels.get(i)))  {
                        fooGroupTreeModels.remove(j);
                    }
                }
            }

        }
        return fooGroupTreeModels;
    }

    /**
     * 根据建筑code和建筑名称判断建筑是否已经存在
     * @param buildingCode 建筑code
     * @param buildingName 建筑名称
     * @return 建筑id
     * @author 段恩刚
     * @since 2.0.0 2018/11/27 19:19
     */
    @Override
    public String findIdIsExist(String buildingCode, String buildingName) {
        return buildingDao.findIdIsExist(buildingCode,buildingName);
    }

    /**
     * 无参查询Building建筑父节点及建筑信息集合BuildingEntity
     * @return List<BuildingEntity>
     * @auther 智雪艳
     * @since 2019/05/23 19:19
     */
    @Override
    public List<BuildingEntity> findBuilding() {
        return buildingDao.findBuilding();
    }
}
